package RateService

import (
	RateModel "blog/app/models/rate_model"
	"blog/config"
	"blog/service"
	"blog/utils"
	"blog/utils/tools"
	"fmt"
	_ "github.com/6tail/lunar-go/calendar"
	"github.com/gin-gonic/gin"
	"strconv"
	"time"
)

// CurrencyCode 汇率编码列表
func CurrencyCode(c *gin.Context) {
	//allCode := c.Query("all")
	// 默认获取主流的几个币种
	var currencyCodes []RateModel.CurrencyName
	err := utils.MySqlDB.Model(&RateModel.CurrencyName{}).
		Where("importance > 1").Find(&currencyCodes).Error
	if err != nil {
		fmt.Println(err)
		service.CommonCJsonReply(c, config.ERROR, "查询失败")
		return
	}
	var currencyMap = make(map[string]string)
	for _, currency := range currencyCodes {
		currencyMap[currency.CurrencyCode] = currency.CurrencyName
	}
	service.CommonCJsonReply(c, config.SUCCESS, currencyMap)
}

// SearchRateByCode 查询一天汇率信息
func SearchRateByCode(c *gin.Context) {
	fromCode := c.Query("from_code")
	toCode := c.Query("to_code")
	date := c.Query("date")

	var rateData []RateModel.RateRecord
	// 查询数据
	err := utils.MySqlDB.Model(&RateModel.RateRecord{}).
		Where("from_code = ? AND to_code = ? AND rate_date = ?", fromCode, toCode, date).
		First(&rateData).Error
	if err != nil {
		// 如果查询记录不存在就返回记录不存在
		if err.Error() == "record not found" {
			service.CommonCJsonReply(c, config.ERROR, "查询记录不存在")
			return
		}
		fmt.Println(err)
		service.CommonCJsonReply(c, config.ERROR, "查询失败")
		return
	}
	service.CommonCJsonReply(c, config.SUCCESS, rateData)
}

// GetRateTrend 查询汇率走势
func GetRateTrend(c *gin.Context) {
	fmt.Println("查询汇率趋势")
	fromCode := c.Query("from_code")
	toCode := c.Query("to_code")
	// 如果form_code为空,就默认使用CNY
	if fromCode == "" {
		fromCode = "CNY"
	}
	// 如果to_code为空,就默认使用USD
	if toCode == "" {
		toCode = "USD"
	}
	// 查询区间 type = 1:近一周 type = 2:近一月 type = 3:近一年 type=4:近五年 获取使用查询区间
	checkType := c.Query("type")
	if checkType == "" {
		// 使用查询区间近一周
		checkType = "1"
	}

	// 查询数据
	var rateData []RateModel.RateRecord
	db := utils.MySqlDB.Model(&RateModel.RateRecord{}).
		Where("from_code = ? AND to_code = ?", fromCode, toCode)

	var opeTime time.Time
	switch checkType {
	case "1":
		opeTime, _ = tools.TryParseTime(tools.GetWeekDate())
		db = db.Where("rate_date >= ?", opeTime)
	case "2":
		opeTime, _ = tools.TryParseTime(tools.GetMonthDate())
		db = db.Where("rate_date >= ?", opeTime)
	case "3":
		opeTime, _ = tools.TryParseTime(tools.GetYearDate())
		db = db.Where("rate_date >= ?", opeTime)
	case "4":
		opeTime, _ = tools.TryParseTime(tools.GetFiveYearDate())
		db = db.Where("rate_date >= ?", opeTime)
	// 如果是 5 就是查询所有
	case "5":
		break
	}
	fmt.Println("操作时间", opeTime)

	err := db.Order("rate_date asc").
		Find(&rateData).Error
	if err != nil {
		// 如果查询记录不存在就返回记录不存在
		if err.Error() == "record not found" {
			service.CommonCJsonReply(c, config.ERROR, "查询记录不存在")
			return
		}
		fmt.Println(err)
		service.CommonCJsonReply(c, config.ERROR, "查询失败")
		return
	}
	var rateMap = make(map[string]float64)
	for _, rate := range rateData {
		rateStr := tools.FormatToDate(rate.RateDate)
		rateMap[rateStr], _ = strconv.ParseFloat(rate.Rate, 64)

	}
	service.CommonCJsonReply(c, config.SUCCESS, rateMap)
}

// GetRateDate 获取汇率日期 日期-> 汇率
func GetRateDate(c *gin.Context) {
	fromCode := c.Query("from_code")
	toCode := c.Query("to_code")
	// 如果form_code为空,就默认使用CNY
	if fromCode == "" {
		fromCode = "CNY"
	}
	// 如果to_code为空,就默认使用USD
	if toCode == "" {
		toCode = "USD"
	}
	// 汇率翻转
	changeCode := c.Query("change_code")
	startDate := c.Query("start_date")
	endDate := c.Query("end_date")
	if startDate == "" {
		startDate = ""
	}
	if endDate == "" {
		endDate = ""
	}
	// 查询数据
	var rateData []RateModel.RateRecord
	db := utils.MySqlDB.Model(&RateModel.RateRecord{}).
		Where("from_code = ? AND to_code = ?",
			fromCode, toCode).
		Where("rate_date >= ? and rate_date < ?", startDate, endDate)

	err := db.Order("rate_date asc").Find(&rateData).Error

	if err != nil {
		// 如果查询记录不存在就返回记录不存在
		if err.Error() == "record not found" {
			service.CommonCJsonReply(c, config.ERROR, "查询记录不存在")
			return
		}
		fmt.Println(err)
		service.CommonCJsonReply(c, config.ERROR, "查询失败")
		return
	}
	var rateMap = make(map[string]float64)
	for _, rate := range rateData {
		rateStr := tools.FormatToDate(rate.RateDate)
		if changeCode != "" {
			// 如果需要翻转汇率
			// 1 rate.Rate string 转换为 float64
			rateChange, _ := strconv.ParseFloat(rate.Rate, 64)
			rateMap[rateStr] = 1 / rateChange
		} else {
			rateMap[rateStr], _ = strconv.ParseFloat(rate.Rate, 64)
		}
	}

	// 获取 rateMap 中 value 最大值和最小值
	var maxRate, minRate float64
	isFirst := true
	for _, rate := range rateMap {
		if isFirst {
			maxRate = rate
			minRate = rate
			isFirst = false
			continue
		}
		if rate > maxRate {
			// 保留两位小数
			maxRate = rate
		}
		if rate < minRate {
			minRate = rate
		}
	}

	c.JSON(config.SUCCESS, gin.H{
		config.ResCode: config.SUCCESS,
		config.ResMsg:  config.GetErrMsg(config.SUCCESS),
		config.ResData: rateMap,
		"max":          maxRate,
		"min":          minRate,
	})
	//service.CommonCJsonReply(c, config.SUCCESS, rateMap)
}

// GetRateLunar 获取汇率 日期/农历 -> 汇率
func GetRateLunar(c *gin.Context) {
	fromCode := c.Query("from_code")
	toCode := c.Query("to_code")
	// 如果form_code为空,就默认使用CNY
	if fromCode == "" {
		fromCode = "CNY"
	}
	// 如果to_code为空,就默认使用USD
	if toCode == "" {
		toCode = "USD"
	}
	// 汇率翻转
	changeCode := c.Query("change_code")
	startDate := c.Query("start_date")
	endDate := c.Query("end_date")
	var fromDate, toDate time.Time
	if startDate == "" {
		fromDate, _ = tools.TryParseTime(tools.GetMonthDate())
	} else {
		fromDate, _ = tools.TryParseTime(startDate)
	}
	if endDate == "" {
		// 默认获取当天的时间
		toDate = time.Now()
	} else {
		toDate, _ = tools.TryParseTime(endDate)
	}
	// 查询数据 - 日期/农历 -> 汇率
	type Result struct {
		RateModel.RateRecord
		LunarMonth string `gorm:"column:lunar_month"`
		LunarDate  string `gorm:"column:lunar_date"`
	}
	var results []Result

	db := utils.MySqlDB.Model(&RateModel.RateRecord{}).
		Select("rate_record.*, lunar_calendar.lunar_month, lunar_calendar.lunar_date, lunar_calendar.holiday").
		Joins("LEFT JOIN lunar_calendar ON DATE(rate_record.rate_date) = DATE(lunar_calendar.date)").
		Where("from_code = ? AND to_code = ?", fromCode, toCode).
		Where("rate_date >= ? and rate_date < ?", fromDate, toDate)

	err := db.Order("rate_date asc").Find(&results).Error
	if err != nil {
		// 如果查询记录不存在就返回记录不存在
		if err.Error() == "record not found" {
			service.CommonCJsonReply(c, config.ERROR, "查询记录不存在")
			return
		}
		fmt.Println(err)
		service.CommonCJsonReply(c, config.ERROR, "查询失败")
		return
	}

	type RateItem struct {
		RateDate  string  `gorm:"column:rate_date"`
		LunarDate string  `gorm:"column:lunar_date"`
		Rate      float64 `gorm:"column:rate"`
	}

	var rateList []RateItem

	for _, rate := range results {
		// 获取这里汇率最大值和最小值,并返回到data中
		rateStr := tools.FormatToDate(rate.RateDate)
		// 组合农历日期信息
		lunarStr := fmt.Sprintf("%s%s", rate.LunarMonth, rate.LunarDate)
		//lunarDate := fmt.Sprintf("%s(%s)", rateStr, lunarStr)
		rateNum, _ := strconv.ParseFloat(rate.Rate, 64)
		if changeCode != "" {
			// 如果需要翻转汇率
			rateList = append(rateList, RateItem{
				RateDate:  rateStr,
				LunarDate: lunarStr,
				Rate:      1 / rateNum,
			})
		} else {
			rateList = append(rateList, RateItem{
				RateDate:  rateStr,
				LunarDate: lunarStr,
				Rate:      rateNum,
			})
		}
	}
	service.CommonCJsonReply(c, config.SUCCESS, rateList)
}

// GetRateByCurrency 获取主位币种对应其他币种的汇率
func GetRateByCurrency(c *gin.Context) {
	fromCode := c.Query("from_code")
	startDate := c.Query("start_date")
	endDate := c.Query("end_date")
	var fromDate, toDate time.Time
	if startDate == "" {
		fromDate, _ = tools.TryParseTime(tools.GetMonthDate())
	} else {
		fromDate, _ = tools.TryParseTime(startDate)
	}
	if endDate == "" {
		// 默认获取当天的时间
		toDate = time.Now()
	} else {
		toDate, _ = tools.TryParseTime(endDate)
	}
	// 如果form_code为空,就默认使用CNY
	if fromCode == "" {
		fromCode = "CNY"
	}
	// 汇率翻转
	changeCode := c.Query("change_code")

	// 默认获取主流的几个币种
	var codeList []string
	if err := utils.MySqlDB.Model(&RateModel.CurrencyName{}).
		Where("importance > 1").
		Pluck("currency_code", &codeList).Error; err != nil {
		service.CommonCJsonReply(c, config.ERROR, "查询失败")
		return
	}
	for i, codeName := range codeList {
		fmt.Println(codeName)
		// 剔除元素和 fromCode 相同的字符串
		if codeName == fromCode {
			codeList = append(codeList[:i], codeList[i+1:]...)
			break
		}
	}
	var rateData []RateModel.RateRecord
	// 查询数据
	db := utils.MySqlDB.Model(&RateModel.RateRecord{}).
		Where("from_code = ? ", fromCode).
		Where("to_code IN (?)", codeList)
	db = db.Where("rate_date >= ? and rate_date < ?", fromDate, toDate)
	err := db.Find(&rateData).Error
	if err != nil {
		// 如果查询记录不存在就返回记录不存在
		if err.Error() == "record not found" {
			service.CommonCJsonReply(c, config.ERROR, "查询记录不存在")
			return
		}
		fmt.Println(err)
		service.CommonCJsonReply(c, config.ERROR, "查询失败")
		return
	}
	// 按日期分组处理数据,返回汇率float64内容
	type RateInfo struct {
		ToCode string  `json:"to_code"`
		Rate   float64 `json:"rate"`
	}
	rateMap := make(map[string][]RateInfo)

	for _, rate := range rateData {
		// 格式化日期为 YYYY-MM-DD
		dateStr := rate.RateDate.Format("2006-01-02")

		// 转换汇率为float64
		rateNum, _ := strconv.ParseFloat(rate.Rate, 64)
		if changeCode != "" {
			fmt.Println("翻转汇率前", rateNum)
			// 如果需要翻转汇率
			rateNum = 1 / rateNum
			fmt.Println("翻转汇率后", rateNum)
		}

		// 创建当前汇率信息
		rateInfo := RateInfo{
			ToCode: rate.ToCode,
			Rate:   rateNum,
		}

		// 添加到对应日期的切片中
		rateMap[dateStr] = append(rateMap[dateStr], rateInfo)
	}

	service.CommonCJsonReply(c, config.SUCCESS, rateMap)
}

// GetDateRateList 查询多个币种的日期-汇率信息列表
func GetDateRateList(c *gin.Context) {
	fromCode := c.Query("from_code")
	startDate := c.Query("start_date")
	endDate := c.Query("end_date")
	var fromDate, toDate time.Time
	if startDate == "" {
		fromDate, _ = tools.TryParseTime(tools.GetMonthDate())
	} else {
		fromDate, _ = tools.TryParseTime(startDate)
	}
	if endDate == "" {
		// 默认获取当天的时间
		toDate = time.Now()
	} else {
		toDate, _ = tools.TryParseTime(endDate)
	}
	// 如果form_code为空,就默认使用CNY
	if fromCode == "" {
		fromCode = "CNY"
	}
	// 汇率翻转
	changeCode := c.Query("change_code")

	// 默认获取主流的几个币种
	var codeList []string
	if err := utils.MySqlDB.Model(&RateModel.CurrencyName{}).
		Where("importance > 1").
		Pluck("currency_code", &codeList).Error; err != nil {
		service.CommonCJsonReply(c, config.ERROR, "查询失败")
		return
	}
	for i, codeName := range codeList {
		// 剔除元素和 fromCode 相同的字符串
		if codeName == fromCode {
			codeList = append(codeList[:i], codeList[i+1:]...)
			break
		}
	}
	var rateData []RateModel.RateRecord
	// 查询数据
	db := utils.MySqlDB.Model(&RateModel.RateRecord{}).
		Where("from_code = ? ", fromCode).
		Where("to_code IN (?)", codeList)
	db = db.Where("rate_date >= ? and rate_date < ?", fromDate, toDate)
	err := db.Find(&rateData).Error
	if err != nil {
		// 如果查询记录不存在就返回记录不存在
		if err.Error() == "record not found" {
			service.CommonCJsonReply(c, config.ERROR, "查询记录不存在")
			return
		}
		fmt.Println(err)
		service.CommonCJsonReply(c, config.ERROR, "查询失败")
		return
	}

	// 定义返回数据结构
	type CurrencyRate struct {
		Max   float64            `json:"max"`
		Min   float64            `json:"min"`
		Rates map[string]float64 `json:"rates"`
	}

	// 按币种分组处理数据
	result := make(map[string]CurrencyRate)

	// 初始化每个币种的数据结构
	for _, code := range codeList {
		result[code] = CurrencyRate{
			Rates: make(map[string]float64),
		}
	}

	// 处理汇率数据
	for _, rate := range rateData {
		// 转换汇率为float64
		rateNum, _ := strconv.ParseFloat(rate.Rate, 64)
		if changeCode != "" {
			rateNum = 1 / rateNum
		}

		// 格式化日期
		dateStr := rate.RateDate.Format("2006-01-02")

		// 获取当前币种的数据
		currencyData := result[rate.ToCode]

		// 更新汇率数据
		currencyData.Rates[dateStr] = rateNum

		// 更新最大最小值
		if len(currencyData.Rates) == 1 {
			currencyData.Max = rateNum
			currencyData.Min = rateNum
		} else {
			if rateNum > currencyData.Max {
				currencyData.Max = rateNum
			}
			if rateNum < currencyData.Min {
				currencyData.Min = rateNum
			}
		}

		// 更新回结果map
		result[rate.ToCode] = currencyData
	}

	service.CommonCJsonReply(c, config.SUCCESS, result)
}
